<?php
class system_session_handler_table extends system_session_model implements system_session_handler_interface {
	
	const MODIFIED_COLUMN = 'modifiedColumn';
	const LIFETIME_COLUMN = 'lifetimeColumn';
	const DATA_COLUMN = 'dataColumn';
	const LIFETIME = 'lifetime';
	const OVERRIDE_LIFETIME = 'overrideLifetime';
	
	protected $_primaryAssignment = null;
	protected $_modifiedColumn = 'modified';
	protected $_lifetimeColumn = 'lifetime';
	protected $_dataColumn = 'data';
	protected $_lifetime = false;
	protected $_overrideLifetime = false;
	protected $_sessionSavePath;
	protected $_sessionName;
	protected $_request = null;
	
	public function __construct($config = array()) {
		$this->_request = system_controller_front::getInstance()->getRequest();
		foreach($config as $key => $value) {
			do {
				switch($key) {
					case self::MODIFIED_COLUMN:
						$this->_modifiedColumn = (string) $value;
						break;
					case self::LIFETIME_COLUMN:
						$this->_lifetimeColumn = (string) $value;
						break;
					case self::DATA_COLUMN:
						$this->_dataColumn = (string) $value;
						break;
					case self::LIFETIME:
						$this->setLifetime($value);
						break;
					case self::OVERRIDE_LIFETIME:
						$this->setOverrideLifetime($value);
						break;
					default:
						break 2;
				}
				unset($config[$key]);
			} while(false);
		}
		
		parent::__construct($config);
		$this->setLifetime($this->_lifetime);
	}
	
	public function __destruct() {
		system_session::writeClose();
	}
	
	public function open($save_path, $name) {
		$this->_sessionSavePath = $save_path;
		$this->_sessionName = $name;
		return true;
	}
	
	public function close() {
		return true;
	}
	
	public function read($id) {
		$return = '';		
		$rows = call_user_func_array(array(&$this, 'find'), array($id));
		if(count($rows)) {
			if($this->_getExpirationTime($row = $rows->current()) > time()) {
				$return = $row->{$this->_dataColumn};
			} else {
				$this->destroy($id);
			}
		}		
		return $return;
	}
	
	public function write($id, $data) {
		$return = false;
		$data = array($this->_modifiedColumn => time(), $this->_dataColumn => (string) $data);
		$data['request_uri'] = substr($this->getRequest()->getRequestUri(), 0, 200);
		$data['passport_id'] = (int) system_passport_instance::getInstance()->getSession()->getId();
		$data['ip'] = $this->getRequest()->getClientIp(true);
		$data['host'] = $this->getRequest()->getHeader('host');
		$rows = call_user_func_array(array(&$this, 'find'), array($id));
		if(count($rows)) {
			$data[$this->_lifetimeColumn] = $this->_getLifetime($rows->current());
			$where = $this->getAdapter()->quoteIdentifier($this->_getPrimaryCol()) . ' = ' . $this->getAdapter()->quote($id);
			if($this->update($data, $where)) {
				$return = true;
			}
		} else {
			$data['user_agent'] = substr($this->getRequest()->getHeader('User-Agent'), 0, 200);
			$data['referer'] = substr($this->getRequest()->getHeader('referer'), 0, 200);
			$data[$this->_lifetimeColumn] = $this->_lifetime;
			$data[$this->_getPrimaryCol()] = $id;
			if($this->insert($data)) {
				$return = true;
			}
		}
		
		return $return;
	}
	
	public function destroy($id) {
		$where = $this->getAdapter()->quoteIdentifier($this->_getPrimaryCol()) . ' = ' . $this->getAdapter()->quote($id);
		if($this->delete($where)) {
			$return = true;
		}
		return false;
	}
	
	public function gc($maxlifetime) {
		$this->delete(
				$this->getAdapter()->quoteIdentifier($this->_modifiedColumn) . 
				' + ' . 
				$this->getAdapter()->quoteIdentifier($this->_lifetimeColumn) . 
				' < ' . $this->getAdapter()->quote(time())
		);
		return true;
	}
	
	protected function setLifetime($lifetime, $overrideLifetime = null) {
		if($lifetime < 0) {
			throw new system_session_exception('lifetime can not < 0');
		} else
			if(empty($lifetime)) {
			$this->_lifetime = (int) ini_get('session.gc_maxlifetime');
		} else {
			$this->_lifetime = (int) $lifetime;
		}
		if($overrideLifetime != null) {
			$this->setOverrideLifetime($overrideLifetime);
		}
		return $this;
	}
	
	protected function getLifetime() {
		return $this->_lifetime;
	}
	
	protected function setOverrideLifetime($overrideLifetime) {
		$this->_overrideLifetime = (boolean) $overrideLifetime;
		return $this;
	}
	
	protected function getOverrideLifetime() {
		return $this->_overrideLifetime;
	}
	
	/**
	 *
	 * @return system_controller_request_http
	 */
	protected function getRequest() {
		return $this->_request;
	}
	
	protected function _getPrimaryCol() {
		if(is_array($this->_primary)) {
			if(count($this->_primary) != 1) {
				throw new system_session_exception('Thre session primary ocl muse only one');
			}
			return implode('', $this->_primary);
		} elseif(is_string($this->_primary)) {
			return $this->_primary;
		}
		throw new system_session_exception('The primary type is error');
	}

	protected function _getLifetime(system_db_table_row_abstract $row) {
		$return = $this->_lifetime;		
		if(!$this->_overrideLifetime) {
			$return = (int) $row->{$this->_lifetimeColumn};
		}		
		return $return;
	}

	protected function _getExpirationTime(system_db_table_row_abstract $row) {
		return (int) $row->{$this->_modifiedColumn} + $this->_getLifetime($row);
	}

}
